﻿using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.Reflection;
using System.Collections.Generic;

namespace ghost
{
    public partial class GhostGUI : Form
    {
        private int ghost_disk_cnt = -1; // 得到需要恢复的硬盘号
        private System.Diagnostics.Process pGhost = null; // 运行Ghost的进程

        public GhostGUI()
        {
            InitializeComponent();
        }

        private void open_btn_Click(object sender, EventArgs e)
        {
            OpenFileDialog file = new OpenFileDialog();
            file.Filter = "Ghost文件|*.gho";
            if (file.ShowDialog() == DialogResult.OK)
            {
                tb_file.Text = file.FileName;
            }
        }

        /// </summary>
        /// 生成文件的Md5值
        /// </summary>
        /// <param name="fileName">文件路径</param>
        /// <returns>返回md5值</returns>
        public string GetMD5HashFromFile(string fileName)
        {
            try
            {
                FileStream file = new FileStream(fileName, System.IO.FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);
                file.Close();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
            }
        }

        /// <summary>
        /// 在界面加载时检查Ghost32.exe是否释放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GhostGUI_Load(object sender, EventArgs e)
        {
            try
            {
                if (!Directory.Exists("c:\\ghost"))
                {   //如果不存在就创建file文件夹
                    Directory.CreateDirectory("c:\\ghost");
                }
                if (!File.Exists("c:\\ghost\\disk0.txt") || GetMD5HashFromFile("c:\\ghost\\disk0.txt") != "4965920531805765aba1bd0e46a61aec")
                {  // 两个文件不存在或者两个文件md5值不一样则需要创建这两个文件
                    FileStream fs_disk = new FileStream("c:\\ghost\\disk0.txt", FileMode.Create);
                    StreamWriter sw_disk = new StreamWriter(fs_disk);
                    sw_disk.Write("select disk 0\r\ndetail disk\r\n");
                    sw_disk.Flush(); sw_disk.Close(); fs_disk.Close();
                }
                if (!File.Exists("c:\\ghost\\disk1.txt") || GetMD5HashFromFile("c:\\ghost\\disk1.txt") != "4a04d09fdba6a50487fed7bf2b7acd18")
                {  // 两个文件不存在或者两个文件md5值不一样则需要创建这两个文件
                    FileStream fs_disk = new FileStream("c:\\ghost\\disk1.txt", FileMode.Create);
                    StreamWriter sw_disk = new StreamWriter(fs_disk);
                    sw_disk.Write("select disk 1\r\ndetail disk\r\n");
                    sw_disk.Flush(); sw_disk.Close(); fs_disk.Close();
                }
                System.Diagnostics.Process p_disk = new System.Diagnostics.Process();
                p_disk.StartInfo.FileName = "diskpart.exe";
                p_disk.StartInfo.Arguments = " /s c:\\ghost\\disk0.txt";
                p_disk.StartInfo.UseShellExecute = false;
                p_disk.StartInfo.RedirectStandardOutput = true;
                p_disk.StartInfo.CreateNoWindow = true;
                p_disk.Start();
                string out_disk0 = p_disk.StandardOutput.ReadToEnd();
                p_disk.WaitForExit();
                p_disk.Close();

                p_disk.StartInfo.Arguments = " /s c:\\ghost\\disk1.txt";
                p_disk.Start();
                string out_disk1 = p_disk.StandardOutput.ReadToEnd();
                p_disk.WaitForExit();
                p_disk.Close();

                int[] flag = new int[] { -1, -1 };
                System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(@".*C.*NTFS.*");
                if (out_disk0.Contains("ID:") && out_disk0.Contains("LUN ID :"))
                {  // 包含这些字符则认为硬盘存在
                    flag[0] = 1;
                    //MessageBox.Show(reg.Match(out_disk0).Value);
                    if (reg.Match(out_disk0).Value != "")
                    {
                        flag[0] = 2;
                    }
                }
                if (out_disk1.Contains("ID") && out_disk1.Contains("LUN ID :"))
                {  // 包含这些字符则认为硬盘存在
                    flag[1] = 1;
                    //MessageBox.Show(reg.Match(out_disk1).Value);
                    if (reg.Match(out_disk1).Value != "")
                    {
                        flag[1] = 2;
                    }
                }
                if (flag[0] > 0 && flag[1] > 0 && flag[0] != flag[1])
                {   // 必须存在2个盘,且两个盘至少有一个匹配成功
                    if (flag[0] == 1) // 磁盘0匹配不成功则说明为需要Ghost的盘
                        ghost_disk_cnt = 1;
                    if (flag[1] == 1) // 磁盘1匹配不成功则说明为需要Ghost的盘
                        ghost_disk_cnt = 2;
                }

                if (File.Exists("c:\\ghost\\ghost32.exe") && GetMD5HashFromFile("c:\\ghost\\ghost32.exe") == "9e87b32ff2fd014a04d1676b69c8df18")
                {  // 如果文件存在且md5值正确则不解压文件
                    return;
                }
                Stream sm = Assembly.GetExecutingAssembly().GetManifestResourceStream("ghost.ghost32.exe");
                byte[] bs = new byte[sm.Length];
                sm.Read(bs, 0, (int)sm.Length);
                FileStream fs = new FileStream("c:\\ghost\\ghost32.exe", FileMode.Create);
                fs.Write(bs, 0, bs.Length);
                fs.Close();
                sm.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                System.Environment.Exit(0);
            }
        }

        /// <summary>
        /// 开始执行Ghost
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void start_btn_Click(object sender, EventArgs e)
        {
            try
            {
                string gho_file = tb_file.Text; // 获取文件名
                if (ghost_disk_cnt == -1)
                {   // 已确认只有一个系统硬盘，避免重复判断硬盘
                    MessageBox.Show("不能恢复系统所在硬盘，请接入其他硬盘！");
                    return;
                }
                if (System.IO.Path.GetExtension(gho_file).ToLower() == ".gho" && File.Exists(gho_file))
                {   // 文件后缀必须为.gho,且文件必须存在
                    start_btn.Enabled = false;
                    pGhost = new System.Diagnostics.Process();
                    pGhost.StartInfo.FileName = "c:\\ghost\\ghost32.exe";
                    pGhost.StartInfo.Arguments = " -clone,mode=load,src=\"" + gho_file + "\",dst=" + ghost_disk_cnt + " -sure -fx";
                    pGhost.Start();
                    timer_gui.Enabled = true;
                }
                else
                {
                    MessageBox.Show("选择的文件后缀不是.gho，或者文件不存在！");
                }
            }
            catch (Exception ex)
            {
                start_btn.Enabled = true;
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer_gui_Tick(object sender, EventArgs e)
        {
            if (pGhost != null && pGhost.HasExited)
            {
                start_btn.Enabled = true;
                timer_gui.Enabled = false;
                pGhost = null;
                if (shutdown_btn.Checked)
                {
                    set_win(0);
                }
                if (reboot_btn.Checked)
                {
                    set_win(1);
                }
            }
        }

        private void set_win(int set)
        {
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo.FileName = "shutdown.exe";
            switch (set)
            {
                case 0:
                    process.StartInfo.Arguments = " -f -s -t 20";
                    break;
                case 1:
                    process.StartInfo.Arguments = " -f -r -t 20";
                    break;
                default:
                    break;
            }
            process.Start();
        }
    }
}
